<template>
  <div class="dynamic-header">
    <img
      v-if="usrInfo.bkImg"
      class="header-backImg"
      :src="usrInfo.bkImg"
      alt=""
      @click="openModal(usrInfo.bkImg)"
    />
    <div class="header-backg" v-else></div>
    <div class="header-backImg__modify" v-if="usrInfo.userId === selfId">
      <avatar-upload
        ref="uploadRef"
        action="/api/dynamic/modifyBkImg"
        @start="startUpload"
        @success="uploadSuccess"
        @error="uploadError"
      >
        <span @click="openFolder">更换封面</span></avatar-upload
      >
      <template v-if="usrInfo.bkImg"
        ><span @click="startUseDefault">默认封面</span>
        <template v-if="isMounted"
          ><confirm-dialog
            to="#dynamic"
            v-model="showConfirm"
            width="60%"
            title="更换默认封面"
            :isLoading="isModifyImg"
            @confirm="useDefaultCover"
            ><p>确定更换为默认封面？</p></confirm-dialog
          ></template
        ></template
      >
    </div>
    <div class="header-title" id="header">
      <SvgIcon
        icon-class="close"
        popper-class="header-title__close"
        @click="emits('closeDialog')"
      />
    </div>
    <div class="personalInfo clearfix">
      <img
        ref="avatarRef"
        class="personalInfo-avatar"
        :src="usrInfo.avatar"
        alt=""
        @click="openInfo"
      />
      <div class="personalInfo-nickName">{{ usrInfo.nickName }}</div>
      <SvgIcon
        icon-class="loading"
        class="spinMess"
        popper-class="accept-loading"
        v-if="usrInfo.userId === selfId && showLoadingDynamic"
      />
    </div>
  </div>
  <transition name="fade">
    <div ref="userInfoRef" v-show="showInfo" class="dynamic-header__user">
      <user-info :user-data="usrInfo" @open-modal="openModal"></user-info>
    </div> </transition
  ><Modal v-model="showModal">
    <img class="img-browser" :src="imgSrc" alt="" />
  </Modal>
</template>

<script lang="ts" setup>
import { ref, watch, nextTick, onMounted } from "vue";
import confirmDialog from "@/components/confirmDialog.vue";
import userInfo from "@/components/userInfo.vue";
import avatarUpload from "@/components/ui-components/avatarUpload.vue";
import { ElMessage } from "element-plus";
import { useDynamicPinia } from "@/pinia/dynamic";

const props = defineProps<{
  usrInfo: User & { bkImg: string };
  selfId: string;
  showLoadingDynamic: boolean;
  // 是否正在请求动态数据
  isRequesting: boolean;
  dynamicEle: HTMLDivElement;
  dynamicDataRef: any;
}>();

const emits = defineEmits<{
  (e: "closeDialog"): void;
}>();

const dynamicStore = useDynamicPinia();

/**
 * 当前用户查看的图片的url
 */
const imgSrc = ref<string>("");
/**
 * 是否显示模态框
 */
const showModal = ref<boolean>(false);
// 浏览图片时打开模态框
const openModal: (url: string) => void = (url: string): void => {
  imgSrc.value = url;
  showModal.value = true;
};

/**
 * 给上传图片组件一个ref属性
 */
const uploadRef = ref<typeof avatarUpload>();
/**
 * 是否正在更换封面
 */
const isModifyImg = ref<boolean>(false);
// 点击更改按钮打开文件夹
const openFolder = () =>
  !props.isRequesting &&
  !isModifyImg.value &&
  !showInfo.value &&
  !props.dynamicDataRef?.showInfo &&
  !props.dynamicDataRef?.showMenu &&
  uploadRef.value?.upload();
// 开始上传头像的操作
const startUpload = () => (isModifyImg.value = true);
/**
 * 上传头像成功后的操作
 * @param src - 新头像的url
 */
const uploadSuccess = (src: string) => {
  isModifyImg.value = false;
  props.usrInfo.bkImg = src;
};
// 上传头像失败后的操作
const uploadError = () => {
  isModifyImg.value = false;
  ElMessage({
    type: "error",
    duration: 1500,
    message: "更换失败",
  });
};

/**
 * 是否显示更改默认封面确认框
 */
const showConfirm = ref<boolean>(false);
// 打开确认框
const startUseDefault = () =>
  !props.isRequesting &&
  !isModifyImg.value &&
  !showInfo.value &&
  !props.dynamicDataRef?.showInfo &&
  !props.dynamicDataRef?.showMenu &&
  !showConfirm.value
    ? (showConfirm.value = true)
    : undefined;

// 开始发送请求更换默认封面
const useDefaultCover = () => {
  if (!isModifyImg.value) {
    isModifyImg.value = true;
    dynamicStore
      .useDefaultCover()
      .then((code) => {
        isModifyImg.value = false;
        showConfirm.value = false;
        if (code !== 1)
          ElMessage({
            type: "error",
            duration: 1500,
            message: "更换失败",
          });
      })
      .catch(() => {
        showConfirm.value = false;
        isModifyImg.value = false;
        ElMessage({
          type: "error",
          duration: 1500,
          message: "更换失败",
        });
      });
  }
};

/**
 * 给用户资料卡片一个ref属性
 */
const userInfoRef = ref<HTMLDivElement>();
/**
 * 是否打开用户的资料卡片
 */
const showInfo = ref<boolean>(false);
/**
 * 给用户头像元素一个ref属性
 */
const avatarRef = ref<HTMLImageElement>();

/**
 * 判断用户所点击的元素是否符合标准
 */
const judgeClick = (e: Event) => {
  const target: HTMLElement = e.target as HTMLElement;
  if (!userInfoRef.value?.contains(target) && !avatarRef.value?.contains(target))
    showInfo.value = false;
};

watch(
  () => showInfo.value,
  (show: boolean) => {
    if (show) document.addEventListener("click", judgeClick);
    else document.removeEventListener("click", judgeClick);
  }
);

// 打开用户信息卡片
const openInfo = (e: MouseEvent) => {
  showInfo.value = true;
  const x: number = e.clientX;
  const y: number = e.clientY;
  const rect = props.dynamicEle?.getBoundingClientRect()!;
  nextTick(() => {
    userInfoRef.value!.style.cssText += `top: ${y - rect.y}px; left: ${
      x - rect.x - userInfoRef.value!.offsetWidth
    }px`;
  });
};

/**
 * 是否开始挂载确认对话框组件
 */
const isMounted = ref<boolean>(false);
onMounted(() => (isMounted.value = true));
</script>

<style lang="scss" scoped>
.fade {
  @include fade(0.15s, ease);
}

.dynamic {
  &-header {
    position: relative;

    .header {
      &-backImg {
        object-fit: cover;
        @include setWidHei(100%, 210px);
        @include noselect();
        cursor: pointer;

        &__modify {
          position: absolute;
          left: 10px;
          bottom: 30px;
          color: #fff;
          font-size: 14px;
          transform: scale(0.8);
          z-index: 1;

          span {
            display: inline-block;
            border: 1px solid #fff;
            padding: 3px 8px;
            margin-right: 22px;
            opacity: 0.8;
            cursor: pointer;
            transition: opacity 0.3s;

            &:hover {
              opacity: 1;
            }
          }
        }
      }

      &-backg {
        @include setWidHei(100%, 210px);
        background-color: rgb(142, 142, 142);
      }

      &-title {
        position: absolute;
        top: 0;
        left: 0;
        right: 0;
        padding: 20px 0;
        cursor: move;

        &__close {
          position: absolute;
          right: 10px;
          top: 6px;
          color: #fff;
          font-size: 22px;
          cursor: pointer;
          border-radius: 50%;
          padding: 3px;
          transition: background-color 0.2s;

          &:hover {
            background-color: rgba(249, 42, 42, 0.877);
          }
        }
      }
    }

    .personalInfo {
      position: relative;
      margin: -40px 0 20px 22px;
      text-align: right;

      &-avatar {
        object-fit: cover;
        @include setWidHei(60px, 60px);
        @include noselect();
        float: right;
        cursor: pointer;
        margin-right: 25px;
        border-radius: 50%;
      }

      &-nickName {
        margin: 7px 105px 0 0;
        font-weight: 700;
        color: #fff;
      }

      .accept-loading {
        float: left;
        font-size: 23px;
        position: absolute;
        top: 50px;
        left: 0;
      }
    }

    &__user {
      position: absolute;
      top: 0;
      box-shadow: 0px 0px 6px rgba(0, 0, 0, 0.12);
      background-color: #fff;
      border-radius: 5px;
      padding: 15px 15px 25px;
      box-sizing: border-box;
      z-index: 1;
    }
  }
}
</style>
